package top.zhangjianyong.tools.indicator.strategy.impl;

import org.springframework.stereotype.Component;
import top.zhangjianyong.tools.entity.ETFData;
import top.zhangjianyong.tools.indicator.context.IndicatorContext;
import top.zhangjianyong.tools.indicator.model.TechnicalIndicatorResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * OBV（能量潮）指标计算器
 * 基于成交量的累积指标，反映资金流向
 *
 * @author zhangjianyong
 * @date 2024/01/01
 */
@Component
public class OBVIndicator extends AbstractIndicator {

    private static final String INDICATOR_NAME = "OBV";

    @Override
    public String getName() {
        return INDICATOR_NAME;
    }

    @Override
    public int getMinDataSize() {
        return 2; // 至少需要2个数据点来计算变化
    }

    @Override
    protected TechnicalIndicatorResult doCalculate(IndicatorContext context) {
        List<ETFData> dataList = context.getDataList();

        if (dataList.isEmpty()) {
            return TechnicalIndicatorResult.failure(getName(), "数据列表为空");
        }

        // 计算OBV
        BigDecimal obv = calculateOBV(dataList);

        // 计算OBV的变化率（相对于前一日）
        BigDecimal obvChangeRate = BigDecimal.ZERO;
        if (dataList.size() >= 2) {
            BigDecimal previousOBV = calculateOBV(dataList.subList(0, dataList.size() - 1));
            if (previousOBV != null && previousOBV.compareTo(BigDecimal.ZERO) != 0) {
                obvChangeRate = obv.subtract(previousOBV)
                    .divide(previousOBV.abs(), 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal(100));
            }
        }

        TechnicalIndicatorResult result = TechnicalIndicatorResult.success(getName());
        result.addValue("obv", obv);
        result.addValue("obv_change_rate", obvChangeRate.setScale(2, RoundingMode.HALF_UP));

        return result;
    }

    /**
     * 计算OBV（能量潮）
     * OBV规则：
     * - 如果今日收盘价 > 昨日收盘价，OBV = 昨日OBV + 今日成交量
     * - 如果今日收盘价 < 昨日收盘价，OBV = 昨日OBV - 今日成交量
     * - 如果今日收盘价 = 昨日收盘价，OBV = 昨日OBV
     */
    private BigDecimal calculateOBV(List<ETFData> dataList) {
        if (dataList.isEmpty()) {
            return BigDecimal.ZERO;
        }

        BigDecimal obv = BigDecimal.ZERO;

        for (int i = 1; i < dataList.size(); i++) {
            ETFData current = dataList.get(i);
            ETFData previous = dataList.get(i - 1);

            BigDecimal currentPrice = current.getValue();
            BigDecimal previousPrice = previous.getValue();
            Long currentVolume = current.getVolume() != null ? current.getVolume() : 0L;

            int comparison = currentPrice.compareTo(previousPrice);

            if (comparison > 0) {
                // 价格上涨，OBV增加
                obv = obv.add(BigDecimal.valueOf(currentVolume));
            } else if (comparison < 0) {
                // 价格下跌，OBV减少
                obv = obv.subtract(BigDecimal.valueOf(currentVolume));
            }
            // 价格不变，OBV不变
        }

        return obv;
    }
}

